﻿using JT808.Protocol;
using JT808.Protocol.Extensions.JT1078.MessageBody;
using Microsoft.Extensions.Logging;
using System;

namespace JT1078.Gateway
{
    /// <summary>
    /// 构建由用户下发指令 
    /// </summary>
    public class TerminalCommandBuild
    {
        private readonly ILogger _logger;
        private readonly IJT808Config _jT808Config;
        private readonly JT808Serializer _jT808Serializer;

        public TerminalCommandBuild(IJT808Config jT808Config, ILogger<TerminalCommandBuild> logger)
        {
            _logger = logger;
            _jT808Config = jT808Config;
            _jT808Serializer = _jT808Config.GetSerializer();
        }

        #region JTT-808

        ///// <summary>
        ///// 0x8802 构建 存储多媒体数据检索
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public BuildTerminalCommandResult BuildQueryMultimediaDataCommand(QueryMediaFileDto input)
        //{
        //    var no = TerminalCommandSerialNo.New();
        //    var r = BuildTerminalCommandResult.New();

        //    r.SerialNo = no;
        //    r.Command = _jT808Serializer.Serialize(new JT808Package()
        //    {
        //        Header = new JT808Header()
        //        {
        //            MsgId = 0x8802,
        //            MsgNum = no,
        //            ManualMsgNum = no,
        //            TerminalPhoneNo = input.SimNo
        //        },
        //        Bodies = new JT808_0x8802()
        //        {

        //        }
        //    });
        //    r.BuildTime = DateTime.Now.AddMinutes(-5);//
        //    return r;
        //}

        ///// <summary>
        ///// 0x8803 构建 存储多媒体数据上传命令
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public BuildTerminalCommandResult BuildUploadMultimediaDataCommand(UploadMediaFileDto input)
        //{
        //    var no = TerminalCommandSerialNo.New();
        //    var r = BuildTerminalCommandResult.New();

        //    var package = new JT808Package
        //    {
        //        Header = new JT808Header
        //        {
        //            MsgId = 0x8803,
        //            MsgNum = no,
        //            ManualMsgNum = no,
        //            TerminalPhoneNo = input.SimNo
        //        },
        //        Bodies = new JT808_0x8803()
        //        {

        //        }
        //    };

        //    r.SerialNo = no;
        //    r.Command = _jT808Serializer.Serialize(package);
        //    r.BuildTime = DateTime.Now.AddMinutes(-5);//
        //    return r;
        //}

        ///// <summary>
        ///// 0x8805 构建  单条存储多媒体数据检索上传命令
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public BuildTerminalCommandResult BuildUploadOneMultimediaDataCommand(UploadMediaFileDto input)
        //{
        //    var no = TerminalCommandSerialNo.New();
        //    var r = BuildTerminalCommandResult.New();

        //    var package = new JT808Package
        //    {
        //        Header = new JT808Header
        //        {
        //            MsgId = 0x8805,
        //            MsgNum = no,
        //            ManualMsgNum = no,
        //            TerminalPhoneNo = input.SimNo
        //        },
        //        Bodies = new JT808_0x8805()
        //        {

        //        }
        //    };

        //    r.SerialNo = no;
        //    r.Command = _jT808Serializer.Serialize(package);
        //    r.BuildTime = DateTime.Now.AddMinutes(-5);//
        //    return r;
        //}

        #endregion

        #region JTT-1078
        /// <summary>
        /// 0x9013 构建 查询音视频属性 指令
        /// </summary>
        /// <param name="terminalPhoneNo"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult Build0x9013Command(string terminalPhoneNo)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(new JT808Package()
            {
                Header = new JT808Header()
                {
                    MsgId = 0x9003,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = terminalPhoneNo
                },
                Bodies = new JT808_0x9003()
                {

                }
            });
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }

        /// <summary>
        /// 0x9101 构建 实时音视频传输请求(直播) 指令
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult BuildLiveCommand(LiveDto input)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(new JT808Package()
            {
                Header = new JT808Header()
                {
                    MsgId = 0x9101,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = input.SimNo
                },
                Bodies = new JT808_0x9101()
                {
                    ChannelNo = (byte)input.ChannelNo,
                    ServerIp = input.ServerIp,
                    StreamType = (byte)input.StreamType,
                    DataType = (byte)input.DataType,
                    TcpPort = input.TcpPort,
                    UdpPort = input.UdpPort
                }
            });
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }
        /// <summary>
        /// 0x9102 构建 实时音视频传输控制 指令
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult BuildLiveControlCommand(LiveControlDto input)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(new JT808Package()
            {
                Header = new JT808Header()
                {
                    MsgId = 0x9102,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = input.SimNo
                },
                Bodies = new JT808_0x9102()
                {
                    ChannelNo = (byte)input.ChannelNo,
                    StreamType = (byte)input.StreamType,
                    ControlCmd = input.ControlCmd,
                    CloseAVData = input.ChannelNo
                }
            });
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }


        
        /// <summary>
        /// 0x9201 构建 远程录像回放请求（点播） 指令
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult BuildVodCommand(VodDto input)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(new JT808Package()
            {
                Header = new JT808Header()
                {
                    MsgId = 0x9201,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = input.SimNo
                },
                Bodies = new JT808_0x9201()
                {
                    ChannelNo = (byte)input.ChannelNo,
                    ServerIp = input.ServerIp,
                    StreamType = (byte)input.StreamType,
                    TcpPort = input.TcpPort,
                    UdpPort = input.UdpPort,
                    BeginTime = input.BeginTime,
                    EndTime = input.EndTime,
                    MediaType = input.MediaType,
                    MemoryType = input.MemoryType,
                    PlaybackWay = input.PlaybackWay,
                    PlaySpeed = input.PlaySpeed,
                    ServerIpLength = (byte)input.ServerIp.Length
                }
            });
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }
        /// <summary>
        /// 0x9202 构建 远程录像回放控制 指令
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult BuildVodControlCommand(VodControlDto input)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(new JT808Package()
            {
                Header = new JT808Header()
                {
                    MsgId = 0x9202,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = input.SimNo
                },
                Bodies = new JT808_0x9202()
                {
                    ChannelNo = (byte)input.ChannelNo,
                    PlaySpeed = input.PlaySpeed,
                    DragPlayPosition = input.DragPlayPosition,
                    PlayControl = input.PlayControl
                }
            });
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }

        /// <summary>
        /// 0x9205 构建 查询媒体资源列表 指令
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult BuildQueryMediaFileCommand(QueryMediaFileDto input)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(new JT808Package()
            {
                Header = new JT808Header()
                {
                    MsgId = 0x9205,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = input.SimNo
                },
                Bodies = new JT808_0x9205()
                {
                    ChannelNo = (byte)input.ChannelNo,
                    AlarmFlag = input.AlarmFlag,
                    MediaType = (byte)input.AVResourceType,
                    BeginTime = input.BeginTime,
                    EndTime = input.EndTime,
                    MemoryType = (byte)input.MemoryType,
                    StreamType = (byte)input.StreamType,
                }
            });
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }

        /// <summary>
        /// 0x9206 构建 上传媒体资源列表 指令（上传到FTP服务器）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public BuildTerminalCommandResult BuildUploadMediaFileCommand(UploadMediaFileDto input)
        {
            var no = TerminalCommandSerialNo.New();
            var r = BuildTerminalCommandResult.New();

            var package = new JT808Package
            {
                Header = new JT808Header
                {
                    MsgId = 0x9206,
                    MsgNum = no,
                    ManualMsgNum = no,
                    TerminalPhoneNo = input.SimNo
                },
                Bodies = new JT808_0x9206()
                {
                    AlarmFlag = (byte)input.AlarmFlag,
                    MediaType = (byte)input.MediaType,
                    BeginTime = input.BegTime,
                    EndTime = input.EndTime,
                    ChannelNo = (byte)input.ChannelNo,
                    StreamType = (byte)input.StreamType,
                    MemoryPositon = (byte)input.MemoryPositon,
                    TaskExcuteCondition = 7, //WI-FI + LAN + 3G/4G
                    FileUploadPath = input.FileUploadPath,
                    FileUploadPathLength = (byte)input.FileUploadPath.Length,
                    ServerIp = input.FtpServerIp,
                    ServerIpLength = (byte)input.FtpServerIp.Length,
                    Port = input.FtpServerPort,
                    UserName = input.FtpServerUserName,
                    UserNameLength = (byte)input.FtpServerUserName.Length,
                    Password = input.FtpServerPassWord,
                    PasswordLength = (byte)input.FtpServerPassWord.Length
                }
            };

            r.SerialNo = no;
            r.Command = _jT808Serializer.Serialize(package);
            r.BuildTime = DateTime.Now.AddMinutes(-5);//
            return r;
        }
        #endregion

    }

    public class BuildTerminalCommandResult
    {
        public static BuildTerminalCommandResult New()
        {
            return new BuildTerminalCommandResult();
        }

        public DateTime BuildTime { get; set; }
        public ushort SerialNo { get; set; }

        public byte[] Command { get; set; }
    }

    public class LiveControlDto
    {
        public string SimNo { get; set; }

        public byte ChannelNo { get; set; }

        /// <summary>
        ///  控制指令 平台可以通过该指令对设备的实时音视频进行控制： 
        ///  0:关闭音视频传输指令 
        ///  1:切换码流（增加暂停和继续） 
        ///  2:暂停该通道所有流的发送 
        ///  3:恢复暂停前流的发送,与暂停前的流类型一致
        ///  4:关闭双向对讲
        /// </summary>
        public byte ControlCmd { get; set; }

        /// <summary>
        /// 关闭音视频类型 0:关闭该通道有关的音视频数据 1:只关闭该通道有关的音频，保留该通道有关的视频 2:只关闭该通道有关的视频，保留该通道有关的音频
        /// </summary>
        public int CloseAVData { get; set; }

        /// <summary>
        /// 切换码流类型,将之前申请的码流切换为新申请的码流，音频与切换前保持一致。 
        /// 新申请的码流为： 0:主码流 1:子码流
        /// </summary>
        public int StreamType { get; set; }
    }
    public class LiveDto
    {
        public string SimNo { get; set; }
        //
        // 摘要:
        //     逻辑通道号
        public byte ChannelNo { get; set; }

        //
        // 摘要:
        //     数据类型 0:音视频 1:视频 2:双向对讲 3:监听 4:中心广播 5:透传
        public byte DataType { get; set; }
        //
        // 摘要:
        //     视频服务器IP地址
        public string ServerIp { get; set; }

        //
        // 摘要:
        //     视频服务器TCP端口号，不使用TCP协议传输时保持默认值0即可（TCP和UDP二选一，当TCP和UDP均非默认值时一般以TCP为准）
        public ushort TcpPort { get; set; }

        //
        // 摘要:
        //     视频服务器UDP端口号，不使用UDP协议传输时保持默认值0即可（TCP和UDP二选一，当TCP和UDP均非默认值时一般以TCP为准）
        public ushort UdpPort { get; set; }

        /// <summary>
        /// 码流类型
        /// 0:所有
        /// 1：主
        /// 2：子
        /// </summary>
        public int StreamType { get; set; }

    }

    public class VodControlDto
    {
        public string SimNo { get; set; }
        //
        // 摘要:
        //     逻辑通道号
        public byte ChannelNo { get; set; }

        /// <summary>
        /// 回放控制 0：开始 1：暂停 2：结束 3：快进 4：关键帧快退播放 5：拖动(到指定位置) 6：关键帧播放
        /// </summary>
        public byte PlayControl { get; set; }


        /// <summary>
        /// 快进或快退倍数，当JT808.Protocol.Extensions.JT1078.MessageBody.JT808_0x9202.PlayControl为3和4时，此字段有效，否则置0
        /// 0：无效 1：1倍 2：2倍 3：4倍 4：8倍 5：16倍
        /// </summary>
        public byte PlaySpeed { get; set; }

        /// <summary>
        ///  拖动回放位置，当JT808.Protocol.Extensions.JT1078.MessageBody.JT808_0x9202.PlayControl为5时有效（必须）
        /// </summary>
        public DateTime DragPlayPosition { get; set; }
    }

    public class VodDto
    {
        public string SimNo { get; set; }
        //
        // 摘要:
        //     逻辑通道号
        public byte ChannelNo { get; set; }

        //
        // 摘要:
        //     音视频类型(媒体类型) 0：audio and video 1：audio 2：video 3：audio or video
        public byte MediaType { get; set; }

        //
        // 摘要:
        //     存储器类型 0：主或灾备存储器 1：主存储器 2：灾备存储器
        public byte MemoryType { get; set; }

        //
        // 摘要:
        //     回放方式 0：正常 1：快进 2：关键帧快退回放 3：关键帧播放 4：单帧上传
        public byte PlaybackWay { get; set; }

        //
        // 摘要:
        //     快进或快退倍数，当JT808.Protocol.Extensions.JT1078.MessageBody.JT808_0x9201.PlaybackWay为1和2时，此字段有效，否则置0
        //     0：无效 1：1倍 2：2倍 3：4倍 4：8倍 5：16倍
        public byte PlaySpeed { get; set; }

        //
        // 摘要:
        //     开始时间，当JT808.Protocol.Extensions.JT1078.MessageBody.JT808_0x9201.PlaybackWay为4时，该字段表示单帧上传时间
        public DateTime BeginTime { get; set; }

        //
        // 摘要:
        //     结束时间，当JT808.Protocol.Extensions.JT1078.MessageBody.JT808_0x9201.PlaybackWay为4时，该字段无效
        public DateTime EndTime { get; set; }

        ////
        //// 摘要:
        ////     数据类型 0:音视频 1:视频 2:双向对讲 3:监听 4:中心广播 5:透传
        //public byte DataType { get; set; }
        //
        // 摘要:
        //     视频服务器IP地址
        public string ServerIp { get; set; }

        //
        // 摘要:
        //     视频服务器TCP端口号，不使用TCP协议传输时保持默认值0即可（TCP和UDP二选一，当TCP和UDP均非默认值时一般以TCP为准）
        public ushort TcpPort { get; set; }

        //
        // 摘要:
        //     视频服务器UDP端口号，不使用UDP协议传输时保持默认值0即可（TCP和UDP二选一，当TCP和UDP均非默认值时一般以TCP为准）
        public ushort UdpPort { get; set; }

        /// <summary>
        /// 码流类型
        /// 0:所有
        /// 1：主
        /// 2：子  码流类型 0：主或子码流 1：主 2：子 如果此通道只传输音频，置为0
        /// </summary>
        public int StreamType { get; set; }

    }

    public class QueryMediaFileDto
    {
        public string SimNo { get; set; }
        /// <summary>
        /// 逻辑通道号
        /// </summary>
        public int ChannelNo { get; set; }
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime BeginTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime EndTime { get; set; }
        /// <summary>
        /// 报警标志
        /// </summary>
        public ulong AlarmFlag { get; set; }
        /// <summary>
        /// 音视频资源类型
        /// 0：音视频
        /// 1：音频
        /// 2：视频
        /// 3：音频或视频
        /// </summary>
        public int AVResourceType { get; set; }
        /// <summary>
        /// 码流类型
        /// 0:所有
        /// 1：主
        /// 2：子
        /// </summary>
        public int StreamType { get; set; }
        /// <summary>
        /// 存储器类型
        /// 0：所有存储器
        /// 1：主存储器
        /// 2：灾备存储器
        /// </summary>
        public int MemoryType { get; set; }
    }

    public class UploadMediaFileDto
    {
        /// <summary>
        /// 终端手机号
        /// </summary>
        public string SimNo { get; set; } = string.Empty;
        /// <summary>
        /// 通道号
        /// </summary>
        public int ChannelNo { get; set; }
        /// <summary>
        /// 音视频资源类型：0-音视频 1-音频 2-视频 3-音频或视频
        /// 默认：0
        /// </summary>
        public int MediaType { get; set; } = 0;
        /// <summary>
        /// 码流类型：0-主码流或子码流 1-主码流 2-子码流
        /// 默认：0
        /// </summary>
        public int StreamType { get; set; } = 0;
        /// <summary>
        /// 存储位置：0-主存储或灾备存储 1-主存储 2-灾备存储
        /// 默认：0
        /// </summary>
        public int MemoryPositon { get; set; } = 0;

        public int AlarmFlag { get; set; }
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime BegTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime EndTime { get; set; }

        public string FileUploadPath { get; set; }
        public string FtpServerPassWord { get; set; }
        public string FtpServerUserName { get; set; }
        public string FtpServerIp { get; set; }
        public ushort FtpServerPort { get; set; }
    }

    public class AdasAlarmAttchFileUploadDto
    {
        public string SimNo { get; set; } = string.Empty;
        public string AlarmNo { get; set; } = string.Empty;
        public string ServerIP { get; set; } = string.Empty;

        public ushort ServerTcpPort { get; set; }
        public ushort ServerUdpPort { get; set; }
    }
}
